#include <iostream>
#include <string>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

using namespace std;

// #pragma pack(1)               // 按照字节对齐
// 联合体union内存对齐的2大规则:
// 1.找到占用字节最多的成员；
// 2.union的字节数必须是占用字节最多的成员的字节的倍数，而且需要能够容纳其他的成员
// 3.字节对齐时, 以最多字节的成员作为union的字节数
typedef union
{
    long val;                   // 8字节
    int buf[5];                 // 20字节
    char str;
} Data;
// #pragma pack()



// 说明：按几字节对齐，是根据结构体的最长类型决定的，这里double是最长的字节，所以按4字节对齐
#pragma pack(1)
typedef struct SData
{
    char str;                   // 1字节
    double dVal;                // 8字节
    int iVal;                   // 4字节
    short sVal;                 // 2字节

} _SData;
#pragma pack()


typedef struct Data_t{
    char m:3;
    char n:5;
    short s;

    unsigned int num:2;             // 最大值: 2^2 -1 = 2
    unsigned int num1:3;            // 最大值：2^3 -1 = 7

    union{
    int a;
    char b;
    };

    int h;
} _Data_t; // __attribute__((packed)) _Data_t;





int main(void)
{
    Data val;
    printf("sizeof(val): %ld\n\n", sizeof(val));

    _SData sd;
    printf("sizeof(sd): %ld\n\n", sizeof(sd));

    _Data_t td;

    td.num = 2;
    td.num1 = 6;     // 1111

    printf("sizeof(td): %ld\n\n", sizeof(td));
    printf("td.num: %u, td.num1: %u\n\n", td.num, td.num1);

    typedef struct Data_s
    {
        unsigned int num:2;
        unsigned int num1:3;
        unsigned int num2:1;
        unsigned int num3:4;
    } __Data_s;

    Data_s ds;
    ds.num = 1;
    ds.num1 = 5;
    ds.num2 = 15;
    ds.num3 = 34;
    printf("sizeof(ds): %lu\n", sizeof(ds));
    
    unsigned int n3 = ds.num3 & 0x0f;
    unsigned int n4 = ds.num1 & 0x07;
    printf("n3: %u, n4: %u\n", n3, n4);
    printf("ds.num: %u, ds.num1: %u, ds.num2: %u, ds.num3: %u\n", ds.num, ds.num1, ds.num2, ds.num3);
    printf("\n");

    // 位运算
    int num = 1; 
    num = num >> 3;
    printf("右移3位 - num: %d\n\n", num);

    num = 3;
    num = num << 3;
    printf("左移3位 - num: %d\n", num);

    num = 24; 
    num = (num >> 3) & 0x3;          // 左移3位 = (num的值除以8)
    printf("高3位 - num: %d\n", num);


    // 大小端判断
    // 地址低 -> 高
    // 小端: 数据低字节序放在内存的低地址处, 数据高字节序放在内存的高地址处
    // 大端: 数据低字节序放在内存的高地址处, 数据高字节序放在内存的低地址处
    // 方法一:  
    num = 1;
    char *p = (char*)&num;          // 指针指向该内存地址
    if ( *p == 1 )
    {
        printf("是小端.\n");    
    }else{
        printf("是大端.\n");
    }

    printf("\n");
    union u
    {
        int val;
        char b;
    } _u;

    _u.val = 1;
    if ( _u.b == 1 )
    {
        printf("小端\n");
    }else{
        printf("大端\n");
    }
    
    class Test
    {
    public:
        Test(int num) : m_num(num){}

    private:
        int m_num;    
    };


    class Test1
    {
    public:
        explicit Test1(int num): m_num(num){}           // 禁止隐式构造

    private:
        int m_num;
    };


    Test t1 = 18;
    Test t2(18);

    Test1 t3 = Test1(18);


    return 0;
}